package ch.ethz.fcl.metrobuzz.data.ltt;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.data.interchange.Interchange;
import ch.ethz.fcl.metrobuzz.data.ltt.node.LTTNode;
import ch.ethz.fcl.metrobuzz.data.scene.basemap.Node;

/**
 * Designed for Long Term Trajectory visualization, abandoned.
 * 
 * 
 * @author Zeng Wei 
 * @email  zeng@arch.ethz.ch
 *
 */
public class TrajectoryGraph {
	private MBData data = null;

	private List<Node> mrtStations = null;

	public final boolean DEBUG = true;

	private int selectedNodeId = -1;
	private Map<Integer, LTTNode> selectedLTTNodeMap = null;

	private Map<LTTNode, Integer> lttNodeIndexMap = null;

	private List<Interchange> interchanges = null;

	private FrequentLTT frequentLTT = null;

	public TrajectoryGraph(MBData data) {
		this.data = data;
	}

	// public void processSelectedNode(int selectedNodeId) {
	// long methodStartTime = System.currentTimeMillis();
	//
	// this.selectedNodeId = selectedNodeId;
	//
	// selectedNodeTrajIdList = new ArrayList<Long>();
	// selectedLTTNodeMap = new HashMap<Integer, LTTNode>();
	// lttNodeIndexMap = new HashMap<LTTNode, Integer>();
	//
	// Map<Long, Float> trajPassTimeMap = data.getScene()
	// .getNode(selectedNodeId).getTrajPassTimeMap();
	// for (Long key : trajPassTimeMap.keySet()) {
	// float time = trajPassTimeMap.get(key);
	// if (time >= MBData.startTime * 900
	// && time <= (MBData.startTime + MBData.period) * 900)
	// selectedNodeTrajIdList.add(key);
	// }
	//
	// for (Long trajIndex : selectedNodeTrajIdList) {
	// SingleTrajectory traj = allTrajIdMap.get(trajIndex);
	// List<Integer> itemList = traj.getNodeIndices();
	// int size = itemList.size();
	//
	// for (int i = 0; i < size; i++) {
	// LTTNode lttNode = selectedLTTNodeMap.get(itemList.get(i));
	// if (lttNode == null) {
	// lttNode = new LTTNode(data.getContainer(), this,
	// itemList.get(i));
	// selectedLTTNodeMap.put(itemList.get(i), lttNode);
	// lttNodeIndexMap.put(lttNode, lttNodeIndexMap.size());
	// }
	//
	// int from = i == 0 ? itemList.get(i) : itemList.get(i - 1);
	// int to = i == itemList.size() - 1 ? itemList.get(i) : itemList
	// .get(i + 1);
	//
	// lttNode.getInterchange().addInterchange(from, to, 1);
	// }
	// }
	//
	// LTTNode selectedNode = selectedLTTNodeMap.get(selectedNodeId);
	// frequentLTT = new FrequentLTT(data);
	// frequentLTT.findFrequentLTT(selectedNode);
	// updateCircos(selectedNodeId);
	//
	// long processTime = System.currentTimeMillis() - methodStartTime;
	// if (DEBUG) {
	// System.out.println(selectedNodeTrajIdList.size()
	// + " trajectories " + selectedLTTNodeMap.size()
	// + " associations found of input " + selectedNodeId + " in "
	// + processTime / 1000.0f + " secs");
	// }
	// }

	protected void updateCircos(int selectedNodeId) {
		LTTNode selectedNode = selectedLTTNodeMap.get(selectedNodeId);

		List<LTTNode> lttNodes = frequentLTT.getFrequentNodes();
		interchanges = new ArrayList<Interchange>();

		for (int i = 0; i < lttNodes.size(); i++) {
			LTTNode node = lttNodes.get(i);

			Interchange interchange = node.getInterchange();
			interchange.setRadius(0.012f);

			if (node.getId() == selectedNodeId) {
				node.setLevel(0);
				node.setDistToSelectedNode(0);
			}
			interchanges.add(interchange);
		}

		float maxValue = 0;
		for (Interchange interchange : interchanges) {
			float value = interchange.getCircos().getData().getTotalSum();
			if (value > maxValue)
				maxValue = value;
		}

		for (Interchange interchange : interchanges)
			interchange.getCircos().setGlobalMax(maxValue);

		for (int i = 0; i < lttNodes.size(); i++) {
			LTTNode node = lttNodes.get(i);
			List<Integer> connectedNodeIndices = node.getInterchange()
					.getConnectedNodeIds();

			for (Integer index : connectedNodeIndices) {
				Interchange connectedInterchange = selectedLTTNodeMap
						.get(index).getInterchange();
				interchanges.get(i).addConnectedInterchange(
						connectedInterchange);
			}
		}

		constructHierarchy(selectedNode);
	}

	private void constructHierarchy(LTTNode node) {
		List<Integer> connectedNodeIndices = node.getInterchange()
				.getConnectedNodeIds();
		for (int i = 0; i < connectedNodeIndices.size(); i++) {
			int connectedNodeIndex = connectedNodeIndices.get(i);

			LTTNode connectedNode = selectedLTTNodeMap.get(connectedNodeIndex);
			if (connectedNode.getLevel() != -1
					&& connectedNode.getLevel() < node.getLevel() + 1)
				continue;

			float newDist = data
					.getScene()
					.getBound()
					.getWorldDist(node.toNode().distance(connectedNode.toNode()));
			connectedNode.setDistToSelectedNode(node.getDistToSelectedNode()
					+ newDist);
			connectedNode.setLevel(node.getLevel() + 1);

			constructHierarchy(connectedNode);
		}
	}

	public MBData getData() {
		return data;
	}

	public Map<Integer, LTTNode> getSelectedLTTNodeMap() {
		return this.selectedLTTNodeMap;
	}

	public List<Interchange> getInterchanges() {
		return interchanges;
	}

	public FrequentLTT getFrequentLTT() {
		return frequentLTT;
	}

	public int getLTTNodeIndex(LTTNode node) {
		return lttNodeIndexMap.get(node);
	}

	public List<Node> getMRTStations() {
		if (mrtStations == null) {
			mrtStations = new ArrayList<Node>();
			for (Node node : data.getScene().getEWNodes())
				if (!mrtStations.contains(node))
					mrtStations.add(node);
			for (Node node : data.getScene().getNSNodes())
				if (!mrtStations.contains(node))
					mrtStations.add(node);
			for (Node node : data.getScene().getNENodes())
				if (!mrtStations.contains(node))
					mrtStations.add(node);
			for (Node node : data.getScene().getCCNodes())
				if (!mrtStations.contains(node))
					mrtStations.add(node);
			for (Node node : data.getScene().getCGNodes())
				if (!mrtStations.contains(node))
					mrtStations.add(node);
		}
		return mrtStations;
	}

	public int getSelectedNodeId() {
		return selectedNodeId;
	}
}
